package com.cyj.dream.admin.persistence.manager.systems;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cyj.dream.admin.contacts.enums.ModuleEnum;
import com.cyj.dream.core.constant.users.UserContext;
import com.cyj.dream.core.constant.users.UserInfoDTO;
import com.cyj.dream.admin.model.system.SysModule;
import com.cyj.dream.admin.model.system.SysRoleModule;
import com.cyj.dream.admin.model.system.SysUserRole;
import com.cyj.dream.admin.model.vo.LeftChildrenVo;
import com.cyj.dream.admin.model.vo.LeftMenuVo;
import com.cyj.dream.admin.persistence.service.ITbSysModuleService;
import com.cyj.dream.admin.persistence.service.ITbSysRoleModuleService;
import com.cyj.dream.admin.persistence.service.ITbSysUserRoleService;
import com.cyj.dream.admin.util.IsEmptyUtils;
import com.cyj.dream.core.constant.enums.ResultCode;
import com.cyj.dream.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: 系统菜单模块服务管理类
 * @BelongsProject: dream-DreamChardonnay
 * @BelongsPackage: com.dream.DreamChardonnay.persistence.manager.systems
 * @Author: ChenYongJia
 * @CreateTime: 2021-04-29 09:48
 * @Email: chen87647213@163.com
 * @Version: 1.0
 */
@Slf4j
@Component
public class SysModuleManager {

    @Autowired
    private ITbSysModuleService iTbSysModuleService;

    @Autowired
    private ITbSysUserRoleService iTbSysUserRoleService;

    @Autowired
    private ITbSysRoleModuleService iTbSysRoleModuleService;

    /**
     * 根据菜单对象信息查询用户菜单树
     *
     * @param sysModule
     * @return java.util.List<com.dream.DreamChardonnay.model.system.SysModule>
     * @date 2021/5/6 9:54
     * @author ChenYongJia
     * @version 1.0
     */
    public List<SysModule> selectSysModuleTree(SysModule sysModule) {
        log.info("进入 SysModuleManager 根据菜单对象信息查询用户菜单树方法，传入参数为：{}", JSONObject.toJSONString(sysModule));
        List<SysModule> listSysModule = this.selectSysModuleParent(ModuleEnum.MODULE_PARENT.getCode());
        listSysModule.stream().forEach(item -> {
            item.setChildren(this.selectSysModuleParent(item.getDreamId()));
        });
        return listSysModule;
    }

    /**
     * 根据用户查询的左侧权限菜单栏
     *
     * @return java.util.List<com.dream.DreamChardonnay.model.vo.LeftMenuVo>
     * @date 2021/6/8 9:45
     * @author ChenYongJia
     * @version 1.0
     */
    public List<LeftMenuVo> selectParentSysModule() {
        log.info("进入 SysModuleManager 根据用户查询左侧权限菜单栏方法");
        UserInfoDTO userInfoDto = UserContext.get();
        if (!IsEmptyUtils.isEmpty(userInfoDto)) {
            // 存储当前用户拥有的菜单模块信息
            Set<Long> sysModuleIdSet = new HashSet<>();

            LambdaQueryWrapper<SysUserRole> roleWrapper = new LambdaQueryWrapper<>();

            roleWrapper.eq(SysUserRole::getSysUserId, userInfoDto.getSysUserId());
            // 查询用户和角色的关系列表
            List<SysUserRole> sysUserRoles = iTbSysUserRoleService.list(roleWrapper);

            // 循环查询角色和模块的关系列表
            sysUserRoles.stream().forEach(item -> {
                LambdaQueryWrapper<SysRoleModule> moduleWrapper = new LambdaQueryWrapper<>();

                moduleWrapper.eq(SysRoleModule::getSysRoleId, item.getSysRoleId());
                List<SysRoleModule> sysRoleModules = iTbSysRoleModuleService.list(moduleWrapper);

                // 循环存入当前用户拥有的菜单模块信息
                sysRoleModules.stream().forEach(items -> {
                    sysModuleIdSet.add(items.getSysModuleId());
                });
            });

            if (!IsEmptyUtils.isEmpty(sysModuleIdSet)) {
                // 查询所拥有的模块信息
                List<SysModule> sysModules = this.selectSysModuleBySysModuleIdList(sysModuleIdSet);

                // 纯子菜单
                List<SysModule> sysModulesList = new ArrayList<>();

                // 父菜单
                List<SysModule> sysModuleSet = new ArrayList<>();
                // 将查到的模块的根节点存储Set
                sysModules.stream().forEach(item -> {
                    if (item.getSysModuleParentId() == 0) {
                        sysModuleSet.add(item);
                    } else {
                        sysModulesList.add(item);
                    }
                });

                log.info("sysModuleSet======>>>", sysModuleSet);

                // 根据权重降序排列
                sysModuleSet.stream().sorted(Comparator.comparing(SysModule::getSysModuleWeight).reversed()).collect(Collectors.toList());
                sysModulesList.stream().sorted(Comparator.comparing(SysModule::getSysModuleWeight).reversed()).collect(Collectors.toList());

                log.info("sysModules======>>>", sysModulesList);

                if (!IsEmptyUtils.isEmpty(sysModules)) {
                    // 返回的左侧菜单数据
                    List<LeftMenuVo> leftMenuVoList = new ArrayList<>();
                    // lambda 表达式forEach中获取元素下标--父节点数据
                    Stream.iterate(0, i -> i + 1).limit(sysModuleSet.size()).forEach(index -> {
                        LeftMenuVo leftMenuVo = new LeftMenuVo();
                        SysModule item = sysModuleSet.get(index);
                        leftMenuVo.setIndex(index + 1);
                        leftMenuVo.setParentId(item.getDreamId());
                        leftMenuVo.setCatalogName(item.getSysModuleName());
                        leftMenuVo.setIcon(item.getSysModuleIcon());
                        leftMenuVo.setWeight(item.getSysModuleWeight());
                        leftMenuVoList.add(leftMenuVo);
                    });

                    // 子节点数据
                    leftMenuVoList.stream().forEach(item -> {
                        List<LeftChildrenVo> list = new ArrayList<>();
                        sysModulesList.stream().forEach(items -> {
                            // 如果父节点id等于子节点的父节点id
                            if (items.getSysModuleParentId().equals(item.getParentId())) {
                                LeftChildrenVo leftChildrenVo = new LeftChildrenVo();
                                leftChildrenVo.setName(items.getSysModuleName());
                                leftChildrenVo.setUrl(items.getSysModulePath());
                                leftChildrenVo.setIcon(items.getSysModuleIcon());
                                leftChildrenVo.setWeight(items.getSysModuleWeight());
                                list.add(leftChildrenVo);
                            }
                        });
                        item.setChildren(list);
                    });

                    return leftMenuVoList;
                } else {
                    return null;
                }
            } else {
                log.error("出现错误：用户未拥有菜单模块权限或查询失败，请联系管理员进行查看！");
                throw new BizException(ResultCode.PARAM_NOT_COMPLETE);
            }
        } else {
            log.error("出现错误：用户未登录或查询失败，请联系管理员进行查看！");
            throw new BizException(ResultCode.USER_TOKEN_IS_INVALID);
        }
    }

    /**
     * 根据用户查询用户所拥有的菜单模块
     *
     * @param sysModule 菜单模块对象
     * @return java.util.List<com.dream.DreamChardonnay.model.system.SysModule>
     * @date 2021/5/6 10:32
     * @author ChenYongJia
     * @version 1.0
     */
    public Map<Long, List<SysModule>> selectSysModuleTreeBySysUser(SysModule sysModule) {
        log.info("进入 SysModuleManager 根据用户查询用户所拥有的菜单模块方法，传入参数为：{}", JSONObject.toJSONString(sysModule));
        UserInfoDTO userInfoDto = UserContext.get();
        if (!IsEmptyUtils.isEmpty(userInfoDto)) {
            // 存储当前用户拥有的菜单模块信息
            Set<Long> sysModuleIdSet = new HashSet<>();

            LambdaQueryWrapper<SysUserRole> roleWrapper = new LambdaQueryWrapper<>();

            roleWrapper.eq(SysUserRole::getSysUserId, userInfoDto.getSysUserId());
            // 查询用户和角色的关系列表
            List<SysUserRole> sysUserRoles = iTbSysUserRoleService.list(roleWrapper);

            // 循环查询角色和模块的关系列表
            sysUserRoles.stream().forEach(item -> {
                LambdaQueryWrapper<SysRoleModule> moduleWrapper = new LambdaQueryWrapper<>();

                moduleWrapper.eq(SysRoleModule::getSysRoleId, item.getSysRoleId());
                List<SysRoleModule> sysRoleModules = iTbSysRoleModuleService.list(moduleWrapper);

                // 循环存入当前用户拥有的菜单模块信息
                sysRoleModules.stream().forEach(items -> {
                    sysModuleIdSet.add(items.getSysModuleId());
                });
            });

            if (!IsEmptyUtils.isEmpty(sysModuleIdSet)) {
                // 查询所拥有的模块信息
                List<SysModule> sysModules = this.selectSysModuleBySysModuleIdList(sysModuleIdSet);

                List<SysModule> sysModulesList = new ArrayList<>();

                Set<SysModule> sysModuleSet = new HashSet<>();
                // 将查到的模块的根节点存储Set
                sysModules.stream().forEach(item -> {
                    if (item.getSysModuleParentId() == 0) {
                        sysModuleSet.add(item);
                    } else {
                        sysModulesList.add(item);
                    }
                });

                // 根据权重降序排列
                sysModuleSet.stream().sorted(Comparator.comparing(SysModule::getSysModuleWeight).reversed()).collect(Collectors.toList());
                sysModulesList.stream().sorted(Comparator.comparing(SysModule::getSysModuleWeight).reversed()).collect(Collectors.toList());

                /**
                 * 第一个参数：分组按照什么分类
                 *
                 * 第二个参数：分组最后用什么容器保存返回
                 *
                 * 第三个参数：按照第一个参数分类后，对应的分类的结果如何收集
                 *
                 * 排列后的数据进行分组
                 */
                Map<Long, List<SysModule>> infoMap = sysModules.stream().collect(Collectors.groupingBy(SysModule::getSysModuleParentId, LinkedHashMap::new, Collectors.toList()));
                log.info("得到的数据为：{}", JSONObject.toJSONString(infoMap));

                return infoMap;
            } else {
                log.error("出现错误：用户未拥有菜单模块权限或查询失败，请联系管理员进行查看！");
                throw new BizException(ResultCode.PARAM_NOT_COMPLETE);
            }
        } else {
            log.error("出现错误：用户未登录或查询失败，请联系管理员进行查看！");
            throw new BizException(ResultCode.USER_TOKEN_IS_INVALID);
        }
    }

    /**
     * 根据菜单id、菜单名称查询菜单信息
     *
     * @param sysModule 菜单对象
     * @return com.dream.DreamChardonnay.model.system.SysModule
     * @date 2021/5/6 8:57
     * @author ChenYongJia
     * @version 1.0
     */
    public SysModule selectBySysModuleName(SysModule sysModule) {
        log.info("进入 SysModuleManager 根据菜单模块名称查询菜单信息方法，传入参数为：{}", JSONObject.toJSONString(sysModule));
        LambdaQueryWrapper<SysModule> wrapper = new LambdaQueryWrapper<>();
        if (!IsEmptyUtils.isEmpty(sysModule.getDreamId())) {
            wrapper.eq(SysModule::getDreamId, sysModule.getDreamId());
        }
        if (!IsEmptyUtils.isEmpty(sysModule.getSysModuleName())) {
            wrapper.like(SysModule::getSysModuleName, sysModule.getSysModuleName());
        }

        // 根据权重降序查询
        wrapper.orderByDesc(SysModule::getSysModuleWeight);

        return iTbSysModuleService.getOne(wrapper);
    }

    /**
     * 根据主键id查询系统菜单信息
     *
     * @param sysModuleId 主键id集合
     * @return java.util.List<com.dream.DreamChardonnay.model.system.SysModule>
     * @date 2021/5/6 11:21
     * @author ChenYongJia
     * @version 1.0
     */
    public List<SysModule> selectSysModuleBySysModuleIdList(Set<Long> sysModuleId) {
        log.info("进入 SysModuleManager 根据主键id查询系统菜单信息方法，参数为：{}", sysModuleId);
        return iTbSysModuleService.listByIds(sysModuleId);
    }

    /**
     * 根据节点信息查询菜单信息
     *
     * @param sysModulesParentId 菜单节点id信息
     * @return 'java.util.List<com.dream.DreamChardonnay.model.system.SysModule>'
     * @date 2021/5/6 9:58
     * @author ChenYongJia
     * @version 1.0
     */
    public List<SysModule> selectSysModuleParent(Long sysModulesParentId) {
        log.info("进入 SysModuleManager 根据菜单id查询菜单信息方法");
        LambdaQueryWrapper<SysModule> wrapper = new LambdaQueryWrapper<>();
        if (sysModulesParentId.equals(ModuleEnum.MODULE_PARENT.getCode())) {
            // 根节点菜单信息
            wrapper.eq(SysModule::getSysModuleParentId, ModuleEnum.MODULE_PARENT);
        } else {
            wrapper.eq(SysModule::getSysModuleParentId, sysModulesParentId);
        }

        return iTbSysModuleService.list(wrapper);
    }

    /**
     * 根据菜单id查询菜单信息
     *
     * @param sysModuleId 菜单id
     * @return java.util.List<com.dream.DreamChardonnay.model.system.SysModule>
     * @date 2021/5/6 10:01
     * @author ChenYongJia
     * @version 1.0
     */
    public SysModule selectModuleByModuleId(Long sysModuleId) {
        log.info("进入 SysModuleManager 根据菜单id查询菜单信息方法，传入参数为：{}", sysModuleId);
        LambdaQueryWrapper<SysModule> wrapper = new LambdaQueryWrapper<>();
        return iTbSysModuleService.getById(sysModuleId);
    }

    /**
     * 添加系统菜单信息
     *
     * @param sysModule 菜单对象
     * @return boolean
     * @date 2021/4/30 9:56
     * @author ChenYongJia
     * @version 1.0
     */
    public boolean addModuleInfo(SysModule sysModule) {
        log.info("进入 SysModuleManager 添加系统菜单信息方法，传入参数为：{}", JSONObject.toJSONString(sysModule));

        UserInfoDTO userInfoDto = UserContext.get();
        /*if (!IsEmptyUtils.isEmpty(this.selectBySysModuleName(sysModule))) {
            log.error("模块名已存在，请重新填写表单后提交");
            throw new BizException(ResultCode.MODULE_HAS_EXISTED);
        }*/

        if (!IsEmptyUtils.isEmpty(userInfoDto)) {
            sysModule.setCreateTime(LocalDateTime.now());
            sysModule.setCreateUserId(userInfoDto.getSysUserId());
        }

        return iTbSysModuleService.save(sysModule);
    }

    /**
     * 修改系统菜单信息
     *
     * @param sysModule 菜单对象
     * @return boolean
     * @date 2021/4/30 9:57
     * @author ChenYongJia
     * @version 1.0
     */
    public boolean updateModuleInfo(SysModule sysModule) {
        log.info("进入 SysModuleManager 修改系统菜单信息方法，传入参数为：{}", JSONObject.toJSONString(sysModule));

        UserInfoDTO userInfoDto = UserContext.get();

        if (!IsEmptyUtils.isEmpty(userInfoDto)) {
            sysModule.setUpdateTime(LocalDateTime.now());
            sysModule.setUpdateUserId(userInfoDto.getSysUserId());
        } else {
            throw new BizException(ResultCode.ERROR);
        }

        return iTbSysModuleService.updateById(sysModule);
    }

    /**
     * 逻辑删除菜单信息
     *
     * @param sysModule 菜单对象
     * @return boolean
     * @date 2021/4/30 9:58
     * @author ChenYongJia
     * @version 1.0
     */
    public boolean deleteModuleInfo(SysModule sysModule) {
        log.info("进入 SysModuleManager 逻辑删除菜单信息方法，传入参数为：{}", JSONObject.toJSONString(sysModule));
        SysModule sysModule1 = this.selectModuleByModuleId(sysModule.getDreamId());
        if(!IsEmptyUtils.isEmpty(sysModule1)){
            List<SysModule> list = this.selectSysModuleParent(sysModule1.getDreamId());
            if(!IsEmptyUtils.isEmpty(list)){
                throw new BizException(ResultCode.ERROR_MODULE_NOT_DEL);
            } else {
                return iTbSysModuleService.removeById(sysModule);
            }
        }
        return false;
    }

    /**
     * 获取所有模块信息
     *
     * @return java.util.List<com.dream.DreamChardonnay.model.system.SysModule>
     * @date 2021-6-10 10:50:14
     * @author ChenYongJia
     * @version 1.0
     */
    public List<SysModule> getModulesLists(){
        log.info("进入 SysModuleManager 获取所有模块信息方法");
        LambdaQueryWrapper<SysModule> wrapper = new LambdaQueryWrapper<>();
        return iTbSysModuleService.list();
    }

}
